Skip to content

chore(ci): add concurrency control to all workflows#48

Open
avrabe wants to merge 1 commit intomainfrom
chore/ci-concurrency-hardening
Open

chore(ci): add concurrency control to all workflows#48
avrabe wants to merge 1 commit intomainfrom
chore/ci-concurrency-hardening

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 2, 2026

Summary

Per the org-wide CI Concurrency Hardening brief. Adds top-level `concurrency:` blocks to all workflow files in `.github/workflows/`. Cancels superseded PR runs; never cancels runs on `main`, releases, or operational state-mutating workflows.

This is the lowest-risk, highest-leverage move available against the 93-job org-wide queue backlog observed in the last 24h.

Classification per file

File Variant applied Notes
`ci.yml` default `cancel-in-progress: ${{ github.event_name == 'pull_request' }}` — cancels superseded PR runs, never main runs (workflow currently only fires on PR but the conditional is future-proofing)
`deploy.yml` release `cancel-in-progress: false` — the deploy script does `find . -delete && tar -xzf` on Netcup; cancelling mid-flight could half-delete prod. Group by `github.ref`
`blog-autopublish.yml` unchanged Already has the correct fixed-group pattern (`group: blog-autopublish, cancel-in-progress: false`). For this workflow that IS correct — it mutates repo state (creates branches, opens PRs), so all runs (cron + workflow_dispatch) must serialize. The brief's "scheduled variant" with `${{ github.run_id }}` would allow concurrent runs and race conditions. Per idempotency rule, leaving as-is.

Out of scope (per brief)

No `runs-on:` changes, no matrix restructuring, no caching changes, no permissions tightening. All those are tracked separately and depend on this PR landing first.

Test plan

  • `ruby -r yaml -e` parses all 3 workflow files
  • All blocks at workflow top level, none inside jobs
  • CI passes
  • Push a follow-up no-op commit to this PR — earlier run must show as Cancelled within ~30s, new run queued
  • After merge: post-merge `main` deploy must complete normally (not cancelled, since deploy uses `cancel-in-progress: false`)

Security

The `concurrency:` blocks use only server-controlled context vars (`github.workflow`, `github.ref`, `github.head_ref`, `github.event_name`). No PR-author-controlled input (issue titles, PR bodies, commit messages) flows into the group key — no command-injection surface.

🤖 Generated with Claude Code

Per the org-wide CI Concurrency Hardening brief. Adds top-level
`concurrency:` blocks to cancel superseded PR runs while preserving
main-branch / scheduled / release runs.

Classification per file:

- ci.yml         → default variant
                   Cancels superseded runs on PRs only; main-branch
                   runs (which this workflow doesn't currently have,
                   but the conditional `cancel-in-progress` is a
                   future-proofing default) are never cancelled.

- deploy.yml     → release variant
                   Never cancels a deploy. The deploy script does
                   `find . -delete && tar -xzf` on Netcup; cancelling
                   mid-flight could leave the site in a half-deleted
                   state. Group by ref so parallel pushes serialize
                   without race-deleting each other.

- blog-autopublish.yml → ALREADY HAS the correct concurrency block
                   (group: blog-autopublish, cancel-in-progress: false).
                   This is a fixed-group pattern that serializes ALL
                   autopublish runs (cron + workflow_dispatch). For
                   this workflow that's correct, NOT the brief's
                   "scheduled variant" with ${{ github.run_id }}: this
                   workflow mutates repo state (creates branches and
                   PRs), so concurrent runs would race. Per idempotency
                   rule, leaving unchanged.

No job-level concurrency. No `runs-on:` changes. No matrix
restructuring. Scope is strictly `.github/workflows/`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant